package edu.etu.sob;

import java.io.IOException;
import java.net.URI;
import java.util.List;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import com.hp.hpl.jena.ontology.OntModel;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.vaadin.Application;
import com.vaadin.data.Item;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.SplitPanel;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.Notification;

import edu.etu.sob.model.impl.OntClassDesc;
import edu.etu.sob.service.IOntologyManager;
import edu.etu.sob.service.OntologyManager;
import edu.etu.sob.ui.NavigationTree;
import edu.etu.sob.util.ClassHierarchy;
import edu.etu.sob.util.DescribeClass;

public class SobMainPage extends Application {
	
	private static final String NS = "http://www.co-ode.org/ontologies/pizza/pizza.owl#";
	
	private Button btnSelect = new Button("Select");
	private Button btnHelp = new Button("Help");
	private SplitPanel horizontalSplit = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL);
	private NavigationTree tree = new NavigationTree();
	
	private IOntologyManager ontologyService = new OntologyManager();
	
	DescribeClass dc;
	
	@Override
	public void init() {
		buildMainLayout();
	}
	
	private DescribeClass getClassDescriptor() {
		if (dc == null)
			dc = new DescribeClass();
		return dc;
	}

	private void buildMainLayout() {
//		setTheme("runo");
		
		setMainWindow(new Window("SOB Application"));
		
		VerticalLayout layout = new VerticalLayout();
		layout.setSizeFull();
		layout.setSpacing(true);
		
		layout.addComponent(createToolbar());
		layout.addComponent(horizontalSplit);
		/* Allocate all available extra space to the horizontal split panel */
        layout.setExpandRatio(horizontalSplit, 1);
        /* Set the initial split position so we can have a 200 pixel menu to the left */
        horizontalSplit.setSplitPosition(200, SplitPanel.UNITS_PIXELS);
        
        tree.setContainerDataSource(buildTree());
        tree.setItemCaptionPropertyId(Constants.PROP_NAME);
        tree.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_PROPERTY);
        tree.addListener(new ClassTreeItemClickListener());
        
        horizontalSplit.setFirstComponent(tree);
        
        setMainComponent(new Label("Test content"));
        
        getMainWindow().setContent(layout);

	}

	private HierarchicalContainer buildTree() {
		HierarchicalContainer container = new HierarchicalContainer();
		container.addContainerProperty(Constants.PROP_URI, String.class, "-");
		container.addContainerProperty(Constants.PROP_NAME, String.class, "-");

		Item item = null;
		int itemId = 0;
		try {
			OntModel model = ontologyService.createOntologyModel("http://www.co-ode.org/ontologies/pizza/pizza.owl");
//			model = ontologyService.createOntologyModel("Ontologies/pizza.owl.rdf");
			
			new ClassHierarchy().showHierarchy(container, model);
		} catch (IOException e) {
			getMainWindow().showNotification("An error occured while reading ontology model", e.toString(), Notification.TYPE_ERROR_MESSAGE);
			e.printStackTrace();
		}
		return container;
	}

	private void setMainComponent(Component c) {
		Component secondComp = horizontalSplit.getSecondComponent();
		if (secondComp != null)
			horizontalSplit.replaceComponent(secondComp, c);
		else
			horizontalSplit.setSecondComponent(c);
	}

	private Component createToolbar() {
		HorizontalLayout lo = new HorizontalLayout();
		lo.addComponent(btnSelect);
		lo.addComponent(btnHelp);
		return lo;
	}
	
	private class ClassTreeItemClickListener implements ItemClickListener {

		@Override
		public void itemClick(ItemClickEvent event) {
    		String uri = event.getItem().getItemProperty(Constants.PROP_URI).getValue().toString();
    		String name = event.getItem().getItemProperty(Constants.PROP_NAME).getValue().toString();
    		
    		System.out.println("item clicked : name : " + name + ", uri : " + uri);


    		// TODO make a common utility
    		ClientConfig config = new DefaultClientConfig();
//    		List<Class<? extends Object>> classes = Arrays.asList(JAXBJSONContextResolver.class, OntClassDesc.class, OntResourceDesc.class, ResourceRestriction.class, LiteralRestriction.class);
//			config.getClasses().addAll(classes);
    		Client client = Client.create(config);
    		WebResource service = client.resource(getBaseURI());
    		String justName = name.substring(1);
			service = service.path("rest").path("classes").path(justName);
			
			OntClassDesc ontClassDesc = service.accept(MediaType.APPLICATION_XML).get(OntClassDesc.class);

			VerticalLayout vl = renderClassDescriptionPanel(uri, ontClassDesc);
    		
			setMainComponent(vl);
		}
		
		private URI getBaseURI() {
			return UriBuilder.fromUri(
					"http://localhost:8080/SOB").build();
		}

		private VerticalLayout renderClassDescriptionPanel(String uri, final OntClassDesc cls) {
			StringBuffer out = new StringBuffer();
			
			VerticalLayout vl = new VerticalLayout();
			vl.setSpacing(true);
			
			// class description
			getClassDescriptor().renderClassDescription(out, cls);
    		Component p1 = createPanelComponent(cls.getUri(), out);
    		vl.addComponent(p1);

            // super-classes
    		out = new StringBuffer();
    		List<OntClassDesc> sc = cls.getSuperClass();
    		for (OntClassDesc ontClassDesc : sc) {
    			out.append( " * " );
                getClassDescriptor().renderClassDescription( out, ontClassDesc );
                out.append("\n");
			}
    		
            if (out.length() > 0) {
	    		Component p2 = createPanelComponent("Super Classes", out);
	    		vl.addComponent(p2);
            }
			return vl;
		}

		private Component createPanelComponent(String title, StringBuffer desc) {
			
			final Panel panel = new Panel(title);
			
			VerticalLayout vl = new VerticalLayout();
			
			vl.addComponent(createPanelRow(desc.toString()));
			
			panel.setContent(vl);

			return panel;
		}

		private Component createPanelRow(String content) {
			return new Label(content, Label.CONTENT_PREFORMATTED);
		}
		
	}

}


